from django.shortcuts import render
from django.views import View
from django.http import JsonResponse
# 导入Django的分页类
from django.core.paginator import Paginator
from apps.goods.models import SKU, GoodsCategory, SKUSpecification, GoodsVisitCount
from haystack.views import SearchView
# 导入封装的商品分类方法
from apps.contents.utils import get_category
# datetime 模块获取日期
from datetime import date


# Create your views here.
class GoodsView(View):
    """
        列表页数据
    """

    def get(self, request, id):
        """

        :param request:
        :param id: 前端传递的三级分类id
        :return:
        """
        # 1、获取前端传递的分页数据和排序数据，查询字符串形式传递
        page = request.GET.get('page')  # 第几页的页数
        page_size = request.GET.get('page_size')  # 每页显示的数量
        ordering = request.GET.get('ordering')  # 排序字段

        # 2、根据前端传递的分类id查询sku表获取对应的商品数据，按照传递的排序数据对所有的商品进行排序

        skus = SKU.objects.filter(category_id=id, is_launched=True).order_by(ordering)

        # 3、对商品数据进行分页处理，使用Django的分页类的方法
        # 3-1 初始化分页类生成分页对象,需要传递两个参数，第一个要分页的数据，第二个分页后每页的数量
        paginator = Paginator(skus, page_size)
        # 3-2 提取分页数据数据，将页数传递的进去，根据传递分页数据进行响应分页数据获取
        try:
            page_skus = paginator.page(page)
        except:
            return JsonResponse({'code': 400}, status=400)

        # 4、构造返回结果
        data_list = []
        for page_sku in page_skus:
            data_list.append({
                'id': page_sku.id,
                'default_image_url': page_sku.default_image.url,
                'name': page_sku.name,
                'price': page_sku.price,
            })

        # 获取当前商品的分类数据，构造面包屑导航数据。查询商品分类表
        cat3 = GoodsCategory.objects.get(id=id)
        # 根据三级分类数据获取二级分类
        cat2 = cat3.parent
        # 根据二级分类数据获取一级分类
        cat1 = cat2.parent

        return JsonResponse({
            'code': 0,
            'errmsg': 'ok',
            "breadcrumb": {  # 面包屑数据
                'cat1': cat1.name,
                'cat2': cat2.name,
                'cat3': cat3.name
            },
            'list': data_list,
            'count': paginator.num_pages  # 分页总数
        })


class GoodsHotView(View):
    """
        热销商品
    """

    def get(self, request, id):
        """

        :param request:
        :param id: 商品的三级分类id
        :return:
        """

        # 1、根据前端传递的分类id查询sku表获取对应的商品数据，按照销量进行排序。数据的控制，返回两条数
        skus = SKU.objects.filter(category_id=id, is_launched=True).order_by('sales')[0:2]
        # 2、构造返回数据的结构
        data_list = []
        for sku in skus:
            data_list.append({
                'id': sku.id,
                'default_image_url': sku.default_image.url,
                'name': sku.name,
                'price': sku.price,
            })

        # 3、返回结果

        return JsonResponse({
            'code': 0,
            'errmsg': 'ok',
            'hot_skus': data_list
        })


class SearchGoodsView(SearchView):
    """
        搜索服务，类视图需要继承haystack客户端的类视图
    """

    # 重写客户单返回结果方法，按照json形式进行返回
    def create_response(self):
        # 获取搜索结果
        context = self.get_context()

        # 同通过context获取查询后的商品数据
        skus = context['page'].object_list
        data_list = []
        for sku in skus:
            data_list.append({
                'id': sku.object.id,
                'name': sku.object.name,
                'price': sku.object.price,
                'default_image_url': sku.object.default_image.url,
                'searchkey': context.get('query'),
                'page_size': context['page'].paginator.num_pages,  # 页数
                'count': context['page'].paginator.count  # 总数
            })

        return JsonResponse(data_list, safe=False)  # 因为返回列表，不在需要进行字典类型检查，所以safe=False


class DetailGoodsView(View):
    """
        详情页数据渲染
    """

    def get(self, request, id):
        """

        :param request:
        :param id: sku商品id
        :return:
        """
        # 1、根据商品id查询sku表获取商品对象
        try:
            sku = SKU.objects.get(id=id)
        except:
            return JsonResponse({'code': 400, 'errmsg': '商品不存在'})
        # 2、获取商品分类数据，调用封装的方法
        categories = get_category()

        # 3、获取面包屑导航数据
        # 获取当前商品的分类数据，构造面包屑导航数据。查询商品分类表
        cat3 = GoodsCategory.objects.get(
            id=sku.category.id)  # 传递分类id,通过sku.category.id 获取到sku对应的商品分类的对象，进而获取商品分类id。sku副表，商品分类是主表
        # 根据三级分类数据获取二级分类
        cat2 = cat3.parent
        # 根据二级分类数据获取一级分类
        cat1 = cat2.parent

        # 对商品的的选项进行选中展示
        # 知道当前商品的选项是什么,获取当前商品的规格，然后根据规格回去对应的选项
        # sku_specs = sku.specs  # 根据主表sku查询副表SKUSpecification，related_name='specs',
        sku_specs = SKUSpecification.objects.filter(sku=sku).order_by('spec_id')
        sku_key = []
        for spec in sku_specs:
            sku_key.append(spec.option_id)
        print(sku_key)

        # 获取所有商品的规格选项，和当前商品进行比对
        # 需要先获取所有sku商品，所有商品和spu有关联关系
        spu = sku.spu  # 副表查询主表
        skus = SKU.objects.filter(spu=spu)  # 获取spu商品系列下的所有内容
        # 字典赋值
        sku_spec_option = {}
        for sku_data in skus:
            s_key = []
            sku_specs = SKUSpecification.objects.filter(sku=sku_data).order_by('spec_id')
            for spec in sku_specs:
                s_key.append(spec.option_id)
            # 将每个sku商品的选项和本身id值进行绑定
            sku_spec_option[tuple(s_key)] = sku_data.id
        # {(11,12):sku_id1,(11,14):sku_id2}
        print(sku_spec_option)

        # 4、渲染规格数据
        # 获取当前商品的所有规格，需要的到当前商品的spu

        goods_specs = spu.specs.all()  # 主表查询副表 在 SPUSpecification表中，关联的spu外键中指定了related_name='specs'参数，那么在进行查询时可以使用该字段来表示副表内容，不在使用副表小写_set形式

        # 遍历规格指定规格选项
        for index, spec in enumerate(goods_specs):
            # 原有规格赋值
            key = sku_key[:]  # 所有下表的数据赋值
            # 根据规格查询该规格下的所有选项  主表查询副表
            spec_options = spec.options.all()
            # 给当前选项赋值sku商品id
            for option in spec_options:
                key[index] = option.id
                option.sku_id = sku_spec_option.get(tuple(key))
            # 在spec中增加一个属性spec_options，spec是遍历的商品规格对象
            spec.spec_options = spec_options
        # 构造渲染数据
        context = {
            'sku': sku,
            'categories': categories,
            'breadcrumb': {  # 面包屑数据
                'cat1': cat1.name,
                'cat2': cat2.name,
                'cat3': cat3.name
            },
            'specs': goods_specs

        }
        # return render(request, 'detail.html', context=context)

        response = render(request, 'detail.html', context=context)
        with open('/Users/august/Desktop/front_end_pc/goods/%d.html' % sku.id, 'w') as f:
            f.write(response.content.decode())

        return JsonResponse({'code': 0})


class DetailVisitView(View):
    """
        商品访问量
    """

    def post(self, request, id):
        """

        :param request:
        :param id: 商品分类id
        :return:
        """
        # 1、根据分类id查询当前分类
        try:
            goods_category = GoodsCategory.objects.get(id=id)
        except:
            return JsonResponse({'code': 400, 'errmsg': '分类不寸在'}, status=400)
        # 2、获取当天日期
        day = date.today()
        # 3、根据分类查询当日期的商品分类统计表
        # 主表查询副表的关联查询
        try:
            # goodvisit = goods_category.goodsvisitcount_set.get(date=day)
            # 直接查询副表，把主表的数据作为过滤条件
            goodvisit = GoodsVisitCount.objects.get(category=goods_category, date=day)
        except:
            # 4、不存在中的生成新的商品分类统计表对象
            goodvisit = GoodsVisitCount()

        # 5、商品分类统计表中的访问数据的累加和分类赋值
        goodvisit.count += 1
        goodvisit.category = goods_category
        goodvisit.save()

        return JsonResponse({'code': 0, 'errmsg': 'ok'})
